<template>
  <el-card style="margin-bottom: 20px">
    <el-row style="text-align: center">
      <el-col :span="4">
        <el-statistic title="正常服务器" :value="serverSuccess" />
      </el-col>
      <el-col :span="5">
        <el-statistic title="异常服务器" :value="serverError" />
      </el-col>
      <el-col :span="5">
        <el-statistic title="运行的微服务" :value="appServerRun" />
      </el-col>
      <el-col :span="5">
        <el-statistic title="启动中的微服务" :value="appServerRuning" />
      </el-col>
      <el-col :span="5">
        <el-statistic title="未启动的微服务" :value="appServerNoRun" />
      </el-col>
    </el-row>
    <el-row>
      <el-col :span="24" />
      <div class="head-all-btns">
        <el-button-group>
          <el-button @click="restartService('', '', '')">重启所有服务</el-button>
          <el-button @click="stopService('', '', '')">停止所有服务</el-button>
          <el-button @click="startService('', '', '')">启动未启动的服务</el-button>
        </el-button-group>
      </div>
    </el-row>
  </el-card>
  <el-tabs type="border-card">
    <el-tab-pane label="服务器">
      <div v-if="servers.length == 0">没有服务器信息</div>
      <el-card class="server-card" v-for="server in servers" :key="server.id">
        <template #header>
          <div class="card-header">
            <el-tag type="danger" v-if="server.serverState == 0">异常</el-tag>
            <el-tag type="success" v-if="server.serverState == 1">正常</el-tag>
            <span class="server-name">{{ server.ip }}({{ server.serverName || '未知' }})</span>
          </div>
          <div class="buttons">
            <el-button-group>
              <el-button v-if="server.serverState == 1" @click="restartServer(server.ip)">
                重启服务器
              </el-button>
              <el-button v-if="server.serverState == 1" @click="restartService(server.ip, '', '')">
                重启所有服务
              </el-button>
              <el-button v-if="server.serverState == 1" @click="stopService(server.ip, '', '')">
                停止所有服务
              </el-button>
              <el-button v-if="server.serverState == 1" @click="startService(server.ip, '', '')">
                启动未启动的服务
              </el-button>
            </el-button-group>
          </div>
          <div style="clear: both"></div>
        </template>
        <el-row>
          <el-col :span="12">
            <el-card class="server-status">
              <el-row>
                <el-col :span="24"> 服务器内存 </el-col>
              </el-row>
              <el-row>
                <el-col :span="6"
                  >总内存：{{ serverMaps[server.ip].health?.memory?.total || 0 }} M</el-col
                >
                <el-col :span="6"
                  >已用内存：{{ serverMaps[server.ip].health?.memory?.used || 0 }} M</el-col
                >
                <el-col :span="6"
                  >可用内存：{{ serverMaps[server.ip].health?.memory?.free || 0 }} M
                </el-col>
                <el-col :span="6"
                  >交换区占用：{{ serverMaps[server.ip].health?.memory?.buffCache || 0 }} M</el-col
                >
              </el-row>
              <el-row>
                <el-col :span="24">
                  <el-progress
                    :percentage="
                      (
                        ((serverMaps[server.ip].health?.memory?.used +
                          serverMaps[server.ip].health?.memory?.buffCache) *
                          100) /
                        serverMaps[server.ip].health?.memory?.total
                      ).toFixed(2)
                    "
                    :color="colors"
                  />
                </el-col>
              </el-row>
              <br />
              <el-row>
                <el-col :span="24"> 服务器CPU </el-col>
                <el-col :span="24">
                  <el-progress
                    :percentage="serverMaps[server.ip].health?.cpu || 0"
                    :color="colors"
                  />
                </el-col>
                <el-col :span="24">
                  <Echart :options="serverMaps[server.ip].echars" :height="350" />
                </el-col>
              </el-row>
              <br />
              <el-row>
                <el-col :span="24">服务器存储 </el-col>
                <el-col :span="24">
                  <el-table
                    :show-overflow-tooltip="true"
                    :highlight-current-row="true"
                    :data="serverMaps[server.ip].health?.disk"
                  >
                    <el-table-column prop="fileSystem" label="文件系统" />
                    <el-table-column prop="size" label="总大小">
                      <template #default="scope">
                        {{ (scope.row.size / 1024).toFixed(2) }}G
                      </template>
                    </el-table-column>
                    <el-table-column prop="used" label="使用空间">
                      <template #default="scope">
                        {{ (scope.row.used / 1024).toFixed(2) }}G
                      </template>
                    </el-table-column>
                    <el-table-column prop="avail" label="剩余空间">
                      <template #default="scope">
                        {{ (scope.row.avail / 1024).toFixed(2) }}G
                      </template>
                    </el-table-column>
                    <el-table-column prop="mounted" label="挂载" />
                    <el-table-column prop="use" label="使用率" />
                  </el-table>
                </el-col>
              </el-row>
            </el-card>
          </el-col>
          <el-col :span="12">
            <el-card class="microservices">
              <el-row v-for="mic in serverMaps[server.ip].service" :key="mic.id">
                <el-col :span="24">
                  <div class="microservice-name">
                    <el-icon color="#e6a23c" v-if="mic.serverMsg">
                      <WarningFilled @click="showWarning(mic.serverMsg)" />
                    </el-icon>
                    <el-tag type="success" v-if="mic.status == 2">运行中</el-tag>
                    <el-tag type="warning" v-if="mic.status == 1">启动中</el-tag>
                    <el-tag type="info" v-if="mic.status == 0">未启动</el-tag>
                    <span class="title">{{ mic.appNote }}({{ mic.appName }}):{{ mic.port }}</span>
                  </div>
                  <div class="microservice-btns">
                    <span v-if="mic.serverState == 0">服务器异常</span>
                    <el-button-group>
                      <el-button
                        size="small"
                        v-if="mic.serverState == 1 && mic.status == 0"
                        @click="startService('', '', mic.id)"
                      >
                        启动服务
                      </el-button>
                      <el-button
                        size="small"
                        v-if="mic.serverState == 1 && mic.status == 2"
                        @click="stopService('', '', mic.id)"
                      >
                        停止服务
                      </el-button>
                      <el-button
                        size="small"
                        v-if="mic.serverState == 1 && mic.status == 2"
                        @click="restartService('', '', mic.id)"
                      >
                        重启服务
                      </el-button>
                    </el-button-group>
                  </div>
                  <div style="clear: both"></div>
                </el-col>
              </el-row>
            </el-card>
          </el-col>
        </el-row>
      </el-card>
    </el-tab-pane>
    <el-tab-pane label="微服务">
      <div v-if="microservices.length == 0">没有微服务信息</div>
      <el-card
        class="microservice-card"
        v-for="microservice in microservices"
        :key="microservice.appName"
      >
        <template #header>
          <div class="card-header">
            <span class="server-name"
              >{{ microservice.appNote || '未知' }}({{ microservice.appName }})</span
            >
          </div>
          <div class="buttons">
            <el-button-group>
              <el-button @click="restartService('', microservice.appName, '')">
                重启所有服务
              </el-button>
              <el-button @click="stopService('', microservice.appName, '')">停止所有服务</el-button>
              <el-button @click="startService('', microservice.appName, '')">
                启动未启动的服务
              </el-button>
            </el-button-group>
          </div>
          <div style="clear: both"></div>
        </template>
        <div
          class="microservice-item"
          v-for="mic in microserviceMaps[microservice.appName].service"
          :key="mic.id"
        >
          <el-row>
            <el-col :span="24">
              <div class="microservice-name">
                <el-icon color="#e6a23c" v-if="mic.serverMsg">
                  <WarningFilled @click="showWarning(mic.serverMsg)" />
                </el-icon>
                <el-tag type="success" v-if="mic.status == 2">运行中</el-tag>
                <el-tag type="warning" v-if="mic.status == 1">启动中</el-tag>
                <el-tag type="info" v-if="mic.status == 0">未启动</el-tag>
                <span class="title">{{ mic.ip }}:{{ mic.port }}</span>
              </div>
              <div class="microservice-btns">
                <span v-if="mic.serverState == 0">服务器异常</span>
                <el-button-group>
                  <el-button
                    size="small"
                    v-if="mic.serverState == 1 && mic.status == 0"
                    @click="startService('', '', mic.id)"
                  >
                    启动服务
                  </el-button>
                  <el-button
                    size="small"
                    v-if="mic.serverState == 1 && mic.status == 2"
                    @click="stopService('', '', mic.id)"
                  >
                    停止服务
                  </el-button>
                  <el-button
                    size="small"
                    v-if="mic.serverState == 1 && mic.status == 2"
                    @click="restartService('', '', mic.id)"
                  >
                    重启服务
                  </el-button>
                </el-button-group>
              </div>
              <div style="clear: both"></div>
            </el-col>
          </el-row>
        </div>
        <div style="clear: both"></div>
      </el-card>
    </el-tab-pane>
  </el-tabs>
  <el-dialog v-model="warningState" title="服务异常信息" width="800">
    <el-scrollbar height="300px">
      {{ warningMessage }}
    </el-scrollbar>
  </el-dialog>
</template>
<script setup lang="ts">
import { Echart } from '@/components/Echart'
import {
  listAppApi,
  listAppServerAllApi,
  restartAppServerApi,
  startAppServerApi,
  stopAppServerApi
} from '@/api/dbms/appserver'
import { listAllApi as listServers, healthApi, restartServerApi } from '@/api/dbms/server'
import { ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useI18n } from '@/hooks/web/useI18n'

const { t } = useI18n()

const colors = [
  { color: '#5cb87a', percentage: 70 },
  { color: '#e6a23c', percentage: 90 },
  { color: '#f56c6c', percentage: 100 }
]

//异常服务器
const serverError = ref(0)

//正常服务器
const serverSuccess = ref(0)

//未运行的服务
const appServerNoRun = ref(0)

//启动中的服务
const appServerRuning = ref(0)

//运行中的服务
const appServerRun = ref(0)

//服务器
const servers = ref<any[]>([])

const serverMaps = ref<any>({})

const serverCpus = ref<any>({})

const loadServers = async () => {
  const rs = await listServers()
  if (rs.success) {
    servers.value = rs.data
    servers.value.forEach((server) => {
      if (server.serverState == 1) {
        serverSuccess.value = serverSuccess.value + 1
      } else {
        serverError.value = serverError.value + 1
      }
      serverCpus.value[server.ip] = []
      serverMaps.value[server.ip] = {
        health: {},
        echars: {
          animation: false,
          title: {
            text: 'CPU使用率'
          },
          tooltip: {
            trigger: 'axis',
            axisPointer: {
              animation: false
            }
          },
          xAxis: {
            type: 'time',
            splitLine: {
              show: false
            }
          },
          yAxis: {
            max: 100,
            type: 'value',
            boundaryGap: [0, '100%'],
            splitLine: {
              show: false
            }
          },
          series: [
            {
              name: 'CPU占用率',
              type: 'line',
              showSymbol: false,
              data: serverCpus.value[server.ip]
            }
          ]
        },
        service: []
      }
      //每秒钟调用异常健康检查
      checkServerkHealth(server.ip)
    })
    loadTimeServers()
  }
}

//每秒刷新服务器状态
const loadTimeServers = async () => {
  const rs = await listServers()
  if (rs.success) {
    servers.value = rs.data
    serverSuccess.value = 0
    serverError.value = 0
    servers.value.forEach((server) => {
      if (server.serverState == 1) {
        serverSuccess.value = serverSuccess.value + 1
      } else {
        serverError.value = serverError.value + 1
      }
    })
  }
  setTimeout(() => {
    loadTimeServers()
  }, 1000)
}

loadServers()

const checkServerkHealth = async (ip) => {
  const rs = await healthApi(ip)
  if (rs.success) {
    serverMaps.value[ip].health = rs.data
    const now = new Date()
    //最多存储100条记录
    if (serverCpus.value[ip].length > 100) {
      serverCpus.value[ip].splice(0, 1)
    }
    serverCpus.value[ip].push({
      name: now,
      value: [now, rs.data.cpu]
    })
  }
  setTimeout(() => {
    checkServerkHealth(ip)
  }, 1000)
}

//微服务
const microservices = ref<any[]>([])
const microserviceMaps = ref<any>({})
const loadApps = async () => {
  const rs = await listAppApi()
  if (rs.success) {
    microservices.value = rs.data
    microservices.value.forEach((m) => {
      microserviceMaps.value[m.appName] = {
        service: []
      }
    })
  }
}
loadApps()

const loadAppServer = async () => {
  const rs = await listAppServerAllApi()
  if (rs.success) {
    appServerNoRun.value = 0
    appServerRun.value = 0
    appServerRuning.value = 0
    const datas = rs.data

    const ips = {}
    const apps = {}
    datas.forEach((as) => {
      if (as.status == 0) {
        appServerNoRun.value = appServerNoRun.value + 1
      }

      if (as.status == 1) {
        appServerRuning.value = appServerRuning.value + 1
      }

      if (as.status == 2) {
        appServerRun.value = appServerRun.value + 1
      }

      if (!ips[as.ip]) {
        ips[as.ip] = []
      }
      if (!apps[as.appName]) {
        apps[as.appName] = []
      }
      ips[as.ip].push(as)
      apps[as.appName].push(as)
    })

    for (const ip in ips) {
      serverMaps.value[ip].service = ips[ip]
    }

    for (const appName in apps) {
      microserviceMaps.value[appName].service = apps[appName]
    }
  }
  setTimeout(() => {
    loadAppServer()
  }, 1000)
}
loadAppServer()

//启动服务
const startService = async (ip: string, appName: string, id: string) => {
  ElMessageBox.confirm('确定启动服务？', t('common.delWarning'), {
    confirmButtonText: t('common.ok'),
    cancelButtonText: t('common.cancel'),
    type: 'warning'
  }).then(async () => {
    const rs = await startAppServerApi(ip, appName, id)
    if (rs.success) {
      ElMessage.success(rs.message)
    }
  })
}
//重启服务
const restartService = async (ip: string, appName: string, id: string) => {
  ElMessageBox.confirm('确定重启服务？', t('common.delWarning'), {
    confirmButtonText: t('common.ok'),
    cancelButtonText: t('common.cancel'),
    type: 'warning'
  }).then(async () => {
    const rs = await restartAppServerApi(ip, appName, id)
    if (rs.success) {
      ElMessage.success(rs.message)
    }
  })
}
//停止服务
const stopService = async (ip: string, appName: string, id: string) => {
  ElMessageBox.confirm('确定停止服务？', t('common.delWarning'), {
    confirmButtonText: t('common.ok'),
    cancelButtonText: t('common.cancel'),
    type: 'warning'
  }).then(async () => {
    const rs = await stopAppServerApi(ip, appName, id)
    if (rs.success) {
      ElMessage.success(rs.message)
    }
  })
}
//重启服务器
const restartServer = async (ip: string) => {
  ElMessageBox.confirm('确定重启服务器？', t('common.delWarning'), {
    confirmButtonText: t('common.ok'),
    cancelButtonText: t('common.cancel'),
    type: 'warning'
  }).then(async () => {
    const rs = await restartServerApi(ip)
    if (rs.success) {
      ElMessage.success(rs.message)
    }
  })
}

const warningState = ref(false)

const warningMessage = ref('')

const showWarning = (msg) => {
  warningMessage.value = msg
  warningState.value = true
}
</script>
<style lang="less" scoped>
.head-all-btns {
  margin-top: 20px;
  width: 100%;
  text-align: right;
}
.server-card,
.microservice-card {
  margin-bottom: 20px;
}
.microservice-card {
  .microservice-item {
    width: calc(50% - 10px);
    float: left;
    margin-right: 10px;
    margin-bottom: 10px;
    .microservice-name {
      float: left;
      .title {
        margin-left: 10px;
      }
    }
    .microservice-btns {
      float: right;
    }
  }
}
.card-header {
  float: left;
  .server-name {
    margin-left: 10px;
  }
}
.buttons {
  float: right;
}
.server-status {
  height: 100%;
}
.microservices {
  margin-left: 20px;
  height: 100%;
  .el-row {
    margin-bottom: 10px;
  }
  .microservice-name {
    float: left;
    .title {
      margin-left: 10px;
    }
  }
  .microservice-btns {
    float: right;
  }
}
</style>
